home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / x / myAsciiSink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  26.2 KB  |  911 lines

  1. /* Borrowed by Jonny Goldman. */
  2. /* $XConsortium: AsciiSink.c,v 1.57 91/07/21 20:35:00 converse Exp $ */
  3.  
  4. /***********************************************************
  5. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  6. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  7.  
  8.                         All Rights Reserved
  9.  
  10. Permission to use, copy, modify, and distribute this software and its 
  11. documentation for any purpose and without fee is hereby granted, 
  12. provided that the above copyright notice appear in all copies and that
  13. both that copyright notice and this permission notice appear in 
  14. supporting documentation, and that the names of Digital or MIT not be
  15. used in advertising or publicity pertaining to distribution of the
  16. software without specific, written prior permission.  
  17.  
  18. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  20. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  21. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  23. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  24. SOFTWARE.
  25.  
  26. ******************************************************************/
  27.  
  28. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  29.  
  30. /*
  31.  * $Log: myAsciiSink.c,v $
  32.  * Revision 1.8  1994/10/31  15:05:12  pfeifer
  33.  * runns under X11R6
  34.  *
  35.  * Revision 1.7  1994/10/21  13:01:17  pfeifer
  36.  * Moved the Log to the top
  37.  *
  38.  * Revision 1.6  1994/10/21  12:50:28  pfeifer
  39.  * Now compiles under X11R6 - query font is invisible :-(
  40.  *
  41.  * Revision 1.5  1994/09/08  16:43:50  pfeifer
  42.  * Added include cdialect.h to enshur, that string.h is included before ctype.h
  43.  *
  44.  * Revision 1.4  1994/08/05  07:25:00  pfeifer
  45.  * Release beta 04
  46.  *
  47.  * Revision 1.3  1994/03/23  19:09:33  pfeifer
  48.  * *** empty log message ***
  49.  *
  50.  * Revision 1.2  93/07/02  18:33:30  warnock
  51.  * included ctype.h
  52.  * 
  53.  * Revision 1.1  1993/02/16  15:10:18  freewais
  54.  * Initial revision
  55.  *
  56.  * Revision 1.2  92/06/22  10:41:17  jonathan
  57.  * Borrowed from Xaw.  Modified to use an alternate font for keyword
  58.  * highlighting.
  59.  * 
  60.  */
  61.  
  62. #include "../ir/cdialect.h"
  63. #include <stdio.h>
  64. #include <ctype.h>
  65.  
  66. #if (XtSpecificationRelease==5)
  67. #include <X11/Xlib.h>
  68. #include <X11/Xutil.h>
  69. #endif /* not XtSpecificationRelease==5 */
  70. #include <X11/Xatom.h>
  71. #include <X11/IntrinsicP.h>
  72. #include <X11/StringDefs.h>
  73. #include <X11/Xaw/XawInit.h>
  74. #include "myAsciiSinkP.h"
  75. #include <X11/Xaw/AsciiSrcP.h>    /* For source function defs. */
  76. #include <X11/Xaw/TextP.h>    /* I also reach into the text widget. */
  77.  
  78. #ifdef GETLASTPOS
  79. #undef GETLASTPOS        /* We will use our own GETLASTPOS. */
  80. #endif
  81.  
  82. #ifndef XawLF
  83. #define XawLF    0x0a
  84. #define XawCR    0x0d
  85. #define XawTAB    0x09
  86. #define XawBS    0x08
  87. #define XawSP    0x20
  88. #define XawDEL    0x7f
  89. #define XawBSLASH    '\\'
  90. #endif
  91.  
  92. #if (XtSpecificationRelease==5)
  93. #define GETLASTPOS XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, TRUE)
  94. #else /* XtSpecificationRelease==5 */
  95. #define GETLASTPOS XawTextSourceScan(source, (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE)
  96. #endif /* XtSpecificationRelease==5 */
  97.  
  98. static void Initialize(), Destroy();
  99. static Boolean SetValues();
  100. #if (XtSpecificationRelease!=5)
  101. static int MaxLines(), MaxHeight();
  102. static void SetTabs();
  103. #endif /* XtSpecificationRelease==5 */
  104.  
  105. static void DisplayText(), InsertCursor(), FindPosition();
  106. static void FindDistance(), Resolve(), GetCursorBounds();
  107.  
  108. #define offset(field) XtOffsetOf(myAsciiSinkRec, ascii_sink.field)
  109.  
  110. static XtResource resources[] = {
  111. #if (XtSpecificationRelease!=5)
  112.     {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  113.     offset(font), XtRString, XtDefaultFont},
  114. #endif /* XtSpecificationRelease==5 */
  115.     {XtNecho, XtCOutput, XtRBoolean, sizeof(Boolean),
  116.     offset(echo), XtRImmediate, (XtPointer) True},
  117.     {XtNdisplayNonprinting, XtCOutput, XtRBoolean, sizeof(Boolean),
  118.     offset(display_nonprinting), XtRImmediate, (XtPointer) True},
  119.     {"altfont", XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  120.        offset(altfont), XtRString, XtDefaultFont},
  121. };
  122. #undef offset
  123.  
  124. #define SuperClass        (&textSinkClassRec)
  125. myAsciiSinkClassRec myasciiSinkClassRec = {
  126.   {
  127. /* core_class fields */    
  128.     /* superclass          */    (WidgetClass) SuperClass,
  129.     /* class_name          */    "MyAsciiSink",
  130.     /* widget_size          */    sizeof(myAsciiSinkRec),
  131.     /* class_initialize       */    XawInitializeWidgetSet,
  132.     /* class_part_initialize    */    NULL,
  133.     /* class_inited           */    FALSE,
  134.     /* initialize          */    Initialize,
  135.     /* initialize_hook        */    NULL,
  136.     /* obj1              */    NULL,
  137.     /* obj2              */    NULL,
  138.     /* obj3              */    0,
  139.     /* resources          */    resources,
  140.     /* num_resources          */    XtNumber(resources),
  141.     /* xrm_class          */    NULLQUARK,
  142.     /* obj4              */    FALSE,
  143.     /* obj5              */    FALSE,
  144.     /* obj6            */    FALSE,
  145.     /* obj7              */    FALSE,
  146.     /* destroy              */    Destroy,
  147.     /* obj8              */    NULL,
  148.     /* obj9              */    NULL,
  149.     /* set_values          */    SetValues,
  150.     /* set_values_hook        */    NULL,
  151.     /* obj10            */    NULL,
  152.     /* get_values_hook        */    NULL,
  153.     /* obj11             */    NULL,
  154.     /* version            */    XtVersion,
  155.     /* callback_private       */    NULL,
  156.     /* obj12               */    NULL,
  157.     /* obj13            */    NULL,
  158.     /* obj14            */    NULL,
  159.     /* extension        */    NULL
  160.   },
  161. /* text_sink_class fields */
  162.   {
  163.     /* DisplayText              */      DisplayText,
  164.     /* InsertCursor             */      InsertCursor,
  165.     /* ClearToBackground        */      XtInheritClearToBackground,
  166.     /* FindPosition             */      FindPosition,
  167.     /* FindDistance             */      FindDistance,
  168.     /* Resolve                  */      Resolve,
  169. #if (XtSpecificationRelease==5)
  170.     /* MaxLines                 */      XtInheritMaxLines,
  171.     /* MaxHeight                */      XtInheritMaxHeight,
  172.     /* SetTabs                  */      XtInheritSetTabs,
  173. #else /* XtSpecificationRelease==5 */
  174.     /* MaxLines                 */      MaxLines,
  175.     /* MaxHeight                */      MaxHeight,
  176.     /* SetTabs                  */      SetTabs,
  177. #endif /* XtSpecificationRelease==5 */
  178.     /* GetCursorBounds          */      GetCursorBounds
  179.   },
  180. /* ascii_sink_class fields */
  181.   {
  182.     /* unused            */    0
  183.   }
  184. };
  185.  
  186. WidgetClass myasciiSinkObjectClass = (WidgetClass)&myasciiSinkClassRec;
  187.  
  188. /* Utilities */
  189.  
  190. static int 
  191. CharWidth (w, x, c, font)
  192. Widget w;
  193. int x;
  194. unsigned char c;
  195. XFontStruct *font;
  196. {
  197.     register int    i, width, nonPrinting;
  198.     myAsciiSinkObject sink = (myAsciiSinkObject) w;
  199.     Position *tab;
  200.  
  201.     if ( c == XawLF ) return(0);
  202.  
  203.     if (c == XawTAB) {
  204.     /* Adjust for Left Margin. */
  205.     x -= ((TextWidget) XtParent(w))->text.margin.left;
  206.  
  207.     if (x >= (int)XtParent(w)->core.width) return 0;
  208.     for (i = 0, tab = sink->text_sink.tabs ; 
  209.          i < sink->text_sink.tab_count ; i++, tab++) {
  210.         if (x < *tab) {
  211.         if (*tab < (int)XtParent(w)->core.width)
  212.             return *tab - x;
  213.         else
  214.             return 0;
  215.         }
  216.     }
  217.     return 0;
  218.     }
  219.  
  220.     if ( (nonPrinting = (c < (unsigned char) XawSP)) )
  221.     if (sink->ascii_sink.display_nonprinting)
  222.         c += '@';
  223.     else {
  224.         c = XawSP;
  225.         nonPrinting = False;
  226.     }
  227.  
  228.     if (font->per_char &&
  229.         (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
  230.     width = font->per_char[c - font->min_char_or_byte2].width;
  231.     else
  232.     width = font->min_bounds.width;
  233.  
  234.     if (nonPrinting)
  235.     width += CharWidth(w, x, (unsigned char) '^', font);
  236.  
  237.     return width;
  238. }
  239.  
  240. /*    Function Name: PaintText
  241.  *    Description: Actually paints the text into the windoe.
  242.  *    Arguments: w - the text widget.
  243.  *                 gc - gc to paint text with.
  244.  *                 x, y - location to paint the text.
  245.  *                 buf, len - buffer and length of text to paint.
  246.  *    Returns: the width of the text painted, or 0.
  247.  *
  248.  * NOTE:  If this string attempts to paint past the end of the window
  249.  *        then this function will return zero.
  250.  */
  251.  
  252. static Dimension
  253. PaintText(w, gc, x, y, buf, len, font)
  254. Widget w;
  255. GC gc;
  256. Position x, y;
  257. unsigned char * buf;
  258. int len;
  259. XFontStruct *font;
  260. {
  261.     myAsciiSinkObject sink = (myAsciiSinkObject) w;
  262.     TextWidget ctx = (TextWidget) XtParent(w);
  263.  
  264.     Position max_x;
  265.     Dimension width = XTextWidth(font, (char *) buf, len); 
  266.     max_x = (Position) ctx->core.width;
  267.  
  268.     if ( ((int) width) <= -x)               /* Don't draw if we can't see it. */
  269.       return(width);
  270.  
  271.     XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc, 
  272.              (int) x, (int) y, (char *) buf, len);
  273.     if ( (((Position) width + x) > max_x) && (ctx->text.margin.right != 0) ) {
  274.     x = ctx->core.width - ctx->text.margin.right;
  275.     width = ctx->text.margin.right;
  276.     XFillRectangle(XtDisplay((Widget) ctx), XtWindow( (Widget) ctx),
  277.                sink->ascii_sink.normgc, (int) x,
  278.                (int) y - font->ascent, 
  279.                (unsigned int) width,
  280.                (unsigned int) (font->ascent +
  281.                        font->descent));
  282.     return(0);
  283.     }
  284.     return(width);
  285. }
  286.  
  287. #define STRINGSIZE 1000
  288.  
  289. int findKeyword(text, keylength)
  290. char *text;
  291. long *keylength;
  292. {
  293.   static char str[STRINGSIZE], *keys, *buf, b1[STRINGSIZE];
  294.   int i, j, k, minpos, offset, pos;
  295.   char c1, c2;
  296.  
  297.   minpos = 999999;
  298.   if((keys = (char*)GetKeywordsUsed()) != NULL) {
  299.  
  300.     if(keylength != NULL && *keylength != 0) {
  301.       buf = b1;
  302.       strncpy(buf, text, *keylength);
  303.       buf[*keylength] = 0;
  304.     }
  305.     else buf = text;
  306.  
  307.     /* parse the keywords into individual words */
  308.     for(j = 0, i = 0; i <= strlen(keys); i++) {
  309.       str[j] = keys[i];
  310.       if ((keys[i] == 0) || 
  311.       isspace(keys[i]) ||
  312.       ispunct(keys[i])) {
  313.     str[j] = 0;
  314.     j = 0;
  315.  
  316.     for(offset = 0, 
  317.         pos = findstring(buf+offset, str, FALSE);
  318.         pos >= 0;
  319.         offset=pos+1, 
  320.         pos = findstring(buf+offset, str, FALSE)) {
  321.       pos+=offset;
  322.       c1 = (pos==0)?' ':buf[pos-1];
  323.       c2 = buf[pos+strlen(str)];
  324.       if(c2==0) c2=' ';
  325.       if((isspace(c1) || ispunct(c1)) &&
  326.          (isspace(c2) || ispunct(c2))) {
  327.         if (pos < minpos) {
  328.           minpos = pos;
  329.           if(keylength != NULL)
  330.         *keylength = strlen(str);
  331.           break;
  332.         }
  333.       }
  334.     }
  335.       }
  336.       else
  337.     j++;
  338.     }
  339.   }
  340.   return minpos;
  341. }
  342.  
  343. /* Sink Object Functions */
  344.  
  345. /*
  346.  * This function does not know about drawing more than one line of text.
  347.  */
  348.  
  349. #ifndef MAXIMUM
  350. #define MAXIMUM(x, y) ((x)>(y)?(x):(y))
  351. #endif
  352. #ifndef MINIMUM
  353. #define MINIMUM(x, y) ((x)<(y)?(x):(y))
  354. #endif
  355.  
  356. static void 
  357. DisplayText(w, x, y, pos1, pos2, highlight)
  358. Widget w;
  359. Position x, y;
  360. Boolean highlight;
  361. XawTextPosition pos1, pos2;
  362. {
  363.   myAsciiSinkObject sink = (myAsciiSinkObject) w;
  364.   Widget source = XawTextGetSource(XtParent(w));
  365.   unsigned char buf[BUFSIZ];
  366.  
  367.   int j, k, keypos, keylen, ws = pos1, we = pos2;
  368.   XawTextBlock blk;
  369.   GC gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc;
  370.   GC invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc;
  371.   GC altgc = highlight ? sink->ascii_sink.invaltgc: sink->ascii_sink.altgc;
  372.   GC invaltgc = highlight? sink->ascii_sink.altgc : sink->ascii_sink.invaltgc;
  373.  
  374. #if (XtSpecificationRelease==5)
  375.   XFontStruct *font = sink->text_sink.font;
  376. #else /* XtSpecificationRelease */
  377.   XFontStruct *font = sink->ascii_sink.font;
  378. #endif /* XtSpecificationRelease */
  379.   XFontStruct *altfont = sink->ascii_sink.altfont;
  380.  
  381.   if (!sink->ascii_sink.echo) return;
  382.  
  383. #if (XtSpecificationRelease==5)
  384.   y += sink->text_sink.font->ascent;
  385. #else /* XtSpecificationRelease */
  386.   y += sink->ascii_sink.font->ascent;
  387. #endif /* XtSpecificationRelease */
  388.   /* adjust positions to word boundaries */
  389.   for(keypos = ws; ws > 0; ws--) {
  390.     XawTextSourceRead(source, ws, &blk, 1);
  391.     if (isspace(blk.ptr[0]) ||
  392.     ispunct(blk.ptr[0])) {
  393.       ws++;
  394.       break;
  395.     }
  396.   }
  397.   for (we=pos2; 
  398.        XawTextSourceRead(source, we, &blk, 1) &&
  399.        (blk.length != 0);
  400.        we++) {
  401.     if (isspace(blk.ptr[0]) ||
  402.     ispunct(blk.ptr[0])) {
  403.       break;
  404.     }
  405.   }
  406.   we = MAXIMUM(we, pos2);
  407.   if(ws != pos1 || we != pos2) {
  408.     XawTextSourceRead(source, ws, &blk, we - ws);
  409.     keylen = blk.length;
  410.     keypos = findKeyword(blk.ptr, &keylen);
  411.     if(keypos == 0) {
  412.       pos1 = XawTextSourceRead(source, pos1, &blk, 
  413.                    MINIMUM((keylen - (pos1 - ws)), (pos2 - pos1)));
  414.       for(j = 0; j < blk.length; j++) buf[j] = blk.ptr[j];
  415. #ifdef USE_ALTFONT        
  416.       x += PaintText(w, altgc, x, y, buf, j, altfont);
  417. #else
  418.       x += PaintText(w, invgc, x, y, buf, j, font);
  419. #endif
  420.     }
  421.   }
  422.   for ( j = 0 ; pos1 < pos2 ; ) {
  423.     pos1 = XawTextSourceRead(source, pos1, &blk, pos2 - pos1);
  424.     keylen = blk.length;
  425.     keypos = findKeyword(blk.ptr, &keylen);
  426.     for (k = 0; k < blk.length; k++) {
  427.       if (k == keypos) {
  428.     x += PaintText(w, gc, x, y, buf, j, font);
  429.     for(j = 0; j < keylen; j++) buf[j] = blk.ptr[k++];
  430. #ifdef USE_ALTFONT        
  431.     x += PaintText(w, altgc, x, y, buf, j, altfont);
  432. #else
  433.     x += PaintText(w, invgc, x, y, buf, j, font);
  434. #endif
  435.     j = 0;
  436.     keylen = blk.length-k;
  437.     keypos = findKeyword((blk.ptr + k), &keylen)+k;
  438.       }
  439.       if (j >= BUFSIZ) {    /* buffer full, dump the text. */
  440.     x += PaintText(w, gc, x, y, buf, j, font);
  441.     j = 0;
  442.       }
  443.       buf[j] = blk.ptr[k];
  444.       if (buf[j] == XawLF)    /* line feeds ('\n') are not printed. */
  445.     continue;
  446.  
  447.       else if (buf[j] == '\t') {
  448.     Position temp = 0;
  449.     Dimension width;
  450.  
  451.     if ((j != 0) && ((temp = PaintText(w, gc, x, y, buf, j, font)) == 0))
  452.       return;
  453.  
  454.     x += temp;
  455.     width = CharWidth(w, x, (unsigned char) '\t', font);
  456.     XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  457.                invgc, (int) x,
  458.                (int) y - font->ascent,
  459.                (unsigned int) width,
  460.                (unsigned int) (font->ascent +
  461.                        font->descent));
  462.     x += width;
  463.     j = -1;
  464.       }
  465.       else if ( buf[j] < (unsigned char) ' ' ) {
  466.     if (sink->ascii_sink.display_nonprinting) {
  467.       buf[j + 1] = buf[j] + '@';
  468.       buf[j] = '^';
  469.       j++;
  470.     }
  471.     else
  472.       buf[j] = ' ';
  473.       }
  474.       j++;
  475.     }
  476.   }
  477.   if (j > 0)
  478.     (void) PaintText(w, gc, x, y, buf, j, font);
  479. }
  480.  
  481.  
  482. #define insertCursor_width 6
  483. #define insertCursor_height 3
  484. static char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
  485.  
  486. static Pixmap
  487. CreateInsertCursor(s)
  488. Screen *s;
  489. {
  490.     return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
  491.           insertCursor_bits, insertCursor_width, insertCursor_height));
  492. }
  493.  
  494. /*    Function Name: GetCursorBounds
  495.  *    Description: Returns the size and location of the cursor.
  496.  *    Arguments: w - the text object.
  497.  * RETURNED        rect - an X rectangle to return the cursor bounds in.
  498.  *    Returns: none.
  499.  */
  500.  
  501. static void
  502. GetCursorBounds(w, rect)
  503. Widget w;
  504. XRectangle * rect;
  505. {
  506.     myAsciiSinkObject sink = (myAsciiSinkObject) w;
  507.  
  508.     rect->width = (unsigned short) insertCursor_width;
  509.     rect->height = (unsigned short) insertCursor_height;
  510.     rect->x = sink->ascii_sink.cursor_x - (short) (rect->width / 2);
  511.     rect->y = sink->ascii_sink.cursor_y - (short) rect->height;
  512. }
  513.  
  514. /*
  515.  * The following procedure manages the "insert" cursor.
  516.  */
  517.  
  518. static void
  519. InsertCursor (w, x, y, state)
  520. Widget w;
  521. Position x, y;
  522. XawTextInsertState state;
  523. {
  524.     myAsciiSinkObject sink = (myAsciiSinkObject) w;
  525.     Widget text_widget = XtParent(w);
  526.     XRectangle rect;
  527.  
  528.     sink->ascii_sink.cursor_x = x;
  529.     sink->ascii_sink.cursor_y = y;
  530.  
  531.     GetCursorBounds(w, &rect);
  532.     if (state != sink->ascii_sink.laststate && XtIsRealized(text_widget)) 
  533.         XCopyPlane(XtDisplay(text_widget),
  534.            sink->ascii_sink.insertCursorOn,
  535.            XtWindow(text_widget), sink->ascii_sink.xorgc,
  536.            0, 0, (unsigned int) rect.width, (unsigned int) rect.height,
  537.            (int) rect.x, (int) rect.y, 1);
  538.     sink->ascii_sink.laststate = state;
  539. }
  540.  
  541. /*
  542.  * Given two positions, find the distance between them.
  543.  */
  544.  
  545. static void
  546. FindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight)
  547. Widget w;
  548. XawTextPosition fromPos;    /* First position. */
  549. int fromx;            /* Horizontal location of first position. */
  550. XawTextPosition toPos;        /* Second position. */
  551. int *resWidth;            /* Distance between fromPos and resPos. */
  552. XawTextPosition *resPos;    /* Actual second position used. */
  553. int *resHeight;            /* Height required. */
  554. {
  555.     myAsciiSinkObject sink = (myAsciiSinkObject) w;
  556.     Widget source = XawTextGetSource(XtParent(w));
  557.  
  558.     register XawTextPosition index, lastPos;
  559.     register unsigned char c;
  560.     XawTextBlock blk;
  561.  
  562.     /* we may not need this */
  563.     lastPos = GETLASTPOS;
  564.     XawTextSourceRead(source, fromPos, &blk, toPos - fromPos);
  565.     *resWidth = 0;
  566.     for (index = fromPos; index != toPos && index < lastPos; index++) {
  567.     if (index - blk.firstPos >= blk.length)
  568.         XawTextSourceRead(source, index, &blk, toPos - fromPos);
  569.     c = blk.ptr[index - blk.firstPos];
  570. #if (XtSpecificationRelease==5)
  571.     *resWidth += CharWidth(w, fromx + *resWidth, c, sink->text_sink.font);
  572. #else /* XtSpecificationRelease */
  573.     *resWidth += CharWidth(w, fromx + *resWidth, c, sink->ascii_sink.font);
  574. #endif /* XtSpecificationRelease */
  575.     if (c == XawLF) {
  576.         index++;
  577.         break;
  578.     }
  579.     }
  580.     *resPos = index;
  581. #if (XtSpecificationRelease==5)
  582.     *resHeight = sink->text_sink.font->ascent +sink->text_sink.font->descent;
  583. #else /* XtSpecificationRelease */
  584.     *resHeight = sink->ascii_sink.font->ascent +sink->ascii_sink.font->descent;
  585. #endif /* XtSpecificationRelease */
  586. }
  587.  
  588.  
  589. static void
  590. FindPosition(w, fromPos, fromx, width, stopAtWordBreak, 
  591.           resPos, resWidth, resHeight)
  592. Widget w;
  593. XawTextPosition fromPos;     /* Starting position. */
  594. int fromx;            /* Horizontal location of starting position.*/
  595. int width;            /* Desired width. */
  596. int stopAtWordBreak;        /* Whether the resulting position should be at
  597.                    a word break. */
  598. XawTextPosition *resPos;    /* Resulting position. */
  599. int *resWidth;            /* Actual width used. */
  600. int *resHeight;            /* Height required. */
  601. {
  602.     myAsciiSinkObject sink = (myAsciiSinkObject) w;
  603.     Widget source = XawTextGetSource(XtParent(w));
  604.  
  605.     XawTextPosition lastPos, index, whiteSpacePosition;
  606.     int     lastWidth, whiteSpaceWidth;
  607.     Boolean whiteSpaceSeen;
  608.     unsigned char c;
  609.     XawTextBlock blk;
  610.  
  611.     lastPos = GETLASTPOS;
  612.  
  613.     XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
  614.     *resWidth = 0;
  615.     whiteSpaceSeen = FALSE;
  616.     c = 0;
  617.     for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
  618.     lastWidth = *resWidth;
  619.     if (index - blk.firstPos >= blk.length)
  620.         XawTextSourceRead(source, index, &blk, BUFSIZ);
  621.     c = blk.ptr[index - blk.firstPos];
  622. #if (XtSpecificationRelease==5)
  623.     *resWidth += CharWidth(w, fromx + *resWidth, c, sink->text_sink.font);
  624. #else /* XtSpecificationRelease */
  625.     *resWidth += CharWidth(w, fromx + *resWidth, c, sink->ascii_sink.font);
  626. #endif /* XtSpecificationRelease */
  627.  
  628.     if ((c == XawSP || c == XawTAB) && *resWidth <= width) {
  629.         whiteSpaceSeen = TRUE;
  630.         whiteSpacePosition = index;
  631.         whiteSpaceWidth = *resWidth;
  632.     }
  633.     if (c == XawLF) {
  634.         index++;
  635.         break;
  636.     }
  637.     }
  638.     if (*resWidth > width && index > fromPos) {
  639.     *resWidth = lastWidth;
  640.     index--;
  641.     if (stopAtWordBreak && whiteSpaceSeen) {
  642.         index = whiteSpacePosition + 1;
  643.         *resWidth = whiteSpaceWidth;
  644.     }
  645.     }
  646.     if (index == lastPos && c != XawLF) index = lastPos + 1;
  647.     *resPos = index;
  648. #if (XtSpecificationRelease==5)
  649.     *resHeight = sink->text_sink.font->ascent +sink->text_sink.font->descent;
  650. #else /* XtSpecificationRelease */
  651.     *resHeight = sink->ascii_sink.font->ascent +sink->ascii_sink.font->descent;
  652. #endif /* XtSpecificationRelease */
  653. }
  654.  
  655. static void
  656. Resolve (w, pos, fromx, width, leftPos, rightPos)
  657. Widget w;
  658. XawTextPosition pos;
  659. int fromx, width;
  660. XawTextPosition *leftPos, *rightPos;
  661. {
  662.     int resWidth, resHeight;
  663.     Widget source = XawTextGetSource(XtParent(w));
  664.  
  665.     FindPosition(w, pos, fromx, width, FALSE, leftPos, &resWidth, &resHeight);
  666.     if (*leftPos > GETLASTPOS)
  667.       *leftPos = GETLASTPOS;
  668.     *rightPos = *leftPos;
  669. }
  670.  
  671. static void
  672. GetGC(sink)
  673. myAsciiSinkObject sink;
  674. {
  675.     XtGCMask valuemask = (GCFont | 
  676.               GCGraphicsExposures | GCForeground | GCBackground );
  677.     XGCValues values;
  678.  
  679. #if (XtSpecificationRelease==5)
  680.     values.font = sink->text_sink.font->fid;
  681. #else /* XtSpecificationRelease */
  682.     values.font = sink->ascii_sink.font->fid;
  683. #endif /* XtSpecificationRelease */
  684.     values.graphics_exposures = (Bool) FALSE;
  685.     
  686.     values.foreground = sink->text_sink.foreground;
  687.     values.background = sink->text_sink.background;
  688.     sink->ascii_sink.normgc = XtGetGC((Widget)sink, valuemask, &values);
  689.     
  690.     values.foreground = sink->text_sink.background;
  691.     values.background = sink->text_sink.foreground;
  692.     sink->ascii_sink.invgc = XtGetGC((Widget)sink, valuemask, &values);
  693.     
  694.     /*if((sink->ascii_sink.altfont = 
  695.     XLoadQueryFont(XtDisplay(sink->object.parent),
  696.                "-*-courier-bold-r-*-*-14-*-*-*-*-*-*-*")) != NULL)*/
  697.     values.font = sink->ascii_sink.altfont->fid;
  698.  
  699.     values.foreground = sink->text_sink.foreground;
  700.     values.background = sink->text_sink.background;
  701.     sink->ascii_sink.altgc = XtGetGC((Widget)sink, valuemask, &values);
  702.     
  703.     values.foreground = sink->text_sink.background;
  704.     values.background = sink->text_sink.foreground;
  705.     sink->ascii_sink.invaltgc = XtGetGC((Widget)sink, valuemask, &values);
  706.     
  707.     values.function = GXxor;
  708.     values.background = (unsigned long) 0L;    /* (pix ^ 0) = pix */
  709.     values.foreground = (sink->text_sink.background ^ 
  710.              sink->text_sink.foreground);
  711.     valuemask = GCGraphicsExposures | GCFunction | GCForeground | GCBackground;
  712.     
  713.     sink->ascii_sink.xorgc = XtGetGC((Widget)sink, valuemask, &values);
  714. }
  715.  
  716.  
  717. /***** Public routines *****/
  718.  
  719. /*    Function Name: Initialize
  720.  *    Description: Initializes the TextSink Object.
  721.  *    Arguments: request, new - the requested and new values for the object
  722.  *                                instance.
  723.  *    Returns: none.
  724.  *
  725.  */
  726.  
  727. #define TAB_COUNT 32
  728.  
  729. /* ARGSUSED */
  730. static void
  731. Initialize(request, new)
  732. Widget request, new;
  733. {
  734.   int tabs[TAB_COUNT], i, tab;
  735.   myAsciiSinkObject sink = (myAsciiSinkObject) new;
  736.  
  737.   GetGC(sink);
  738.     
  739.   sink->ascii_sink.insertCursorOn= CreateInsertCursor(XtScreenOfObject(new));
  740.   sink->ascii_sink.laststate = XawisOff;
  741.   sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0;
  742.  
  743.   for (i=0, tab=0 ; i < TAB_COUNT ; i++) 
  744.     tabs[i] = (tab += 8);
  745.   
  746.   XawTextSinkSetTabs((Widget)sink, TAB_COUNT, tabs);
  747. }
  748.  
  749. /*    Function Name: Destroy
  750.  *    Description: This function cleans up when the object is 
  751.  *                   destroyed.
  752.  *    Arguments: w - the AsciiSink Object.
  753.  *    Returns: none.
  754.  */
  755.  
  756. static void
  757. Destroy(w)
  758. Widget w;
  759. {
  760.    myAsciiSinkObject sink = (myAsciiSinkObject) w;
  761.  
  762.    XtReleaseGC(w, sink->ascii_sink.normgc);
  763.    XtReleaseGC(w, sink->ascii_sink.invgc);
  764.    XtReleaseGC(w, sink->ascii_sink.xorgc);
  765.    XtReleaseGC(w, sink->ascii_sink.altgc);
  766.    XtReleaseGC(w, sink->ascii_sink.invaltgc);
  767.    XFreePixmap(XtDisplayOfObject(w), sink->ascii_sink.insertCursorOn);
  768. }
  769.  
  770. /*    Function Name: SetValues
  771.  *    Description: Sets the values for the AsciiSink
  772.  *    Arguments: current - current state of the object.
  773.  *                 request - what was requested.
  774.  *                 new - what the object will become.
  775.  *    Returns: True if redisplay is needed.
  776.  */
  777.  
  778. /* ARGSUSED */
  779. static Boolean
  780. SetValues(current, request, new)
  781. Widget current, request, new;
  782. {
  783.     myAsciiSinkObject w = (myAsciiSinkObject) new;
  784.     myAsciiSinkObject old_w = (myAsciiSinkObject) current;
  785.  
  786. #if (XtSpecificationRelease==5)
  787.     if (w->text_sink.font != old_w->text_sink.font
  788. #else /* XtSpecificationRelease */
  789.     if (w->ascii_sink.font != old_w->ascii_sink.font
  790. #endif /* XtSpecificationRelease */
  791.     || w->ascii_sink.altfont != old_w->ascii_sink.altfont
  792.     || w->text_sink.background != old_w->text_sink.background
  793.     || w->text_sink.foreground != old_w->text_sink.foreground) {
  794.     XtReleaseGC((Widget)w, w->ascii_sink.normgc);
  795.     XtReleaseGC((Widget)w, w->ascii_sink.invgc);
  796.     XtReleaseGC((Widget)w, w->ascii_sink.xorgc);
  797.     XtReleaseGC((Widget)w, w->ascii_sink.altgc);
  798.     XtReleaseGC((Widget)w, w->ascii_sink.invaltgc);
  799.     GetGC(w);
  800.     ((TextWidget)XtParent(new))->text.redisplay_needed = True;
  801.     } else {
  802.     if ( (w->ascii_sink.echo != old_w->ascii_sink.echo) ||
  803.          (w->ascii_sink.display_nonprinting != 
  804.                                      old_w->ascii_sink.display_nonprinting) )
  805.         ((TextWidget)XtParent(new))->text.redisplay_needed = True;
  806.     }
  807.     
  808.     return False;
  809. }
  810.  
  811. #if (XtSpecificationRelease!=5)
  812. /*    Function Name: MaxLines
  813.  *    Description: Finds the Maximum number of lines that will fit in
  814.  *                   a given height.
  815.  *    Arguments: w - the AsciiSink Object.
  816.  *                 height - height to fit lines into.
  817.  *    Returns: the number of lines that will fit.
  818.  */
  819.  
  820. /* ARGSUSED */
  821. static int
  822. MaxLines(w, height)
  823. Widget w;
  824. Dimension height;
  825. {
  826.   myAsciiSinkObject sink = (myAsciiSinkObject) w;
  827.   int font_height;
  828.  
  829.   font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent;
  830.   return( ((int) height) / font_height );
  831. }
  832.  
  833. /*    Function Name: MaxHeight
  834.  *    Description: Finds the Minium height that will contain a given number 
  835.  *                   lines.
  836.  *    Arguments: w - the myAsciiSink Object.
  837.  *                 lines - the number of lines.
  838.  *    Returns: the height.
  839.  */
  840.  
  841. /* ARGSUSED */
  842. static int
  843. MaxHeight(w, lines)
  844. Widget w;
  845. int lines;
  846. {
  847.   myAsciiSinkObject sink = (myAsciiSinkObject) w;
  848.  
  849.   return(lines * (sink->ascii_sink.font->ascent + 
  850.           sink->ascii_sink.font->descent));
  851. }
  852.  
  853. /*    Function Name: SetTabs
  854.  *    Description: Sets the Tab stops.
  855.  *    Arguments: w - the myAsciiSink Object.
  856.  *                 tab_count - the number of tabs in the list.
  857.  *                 tabs - the text positions of the tabs.
  858.  *    Returns: none
  859.  */
  860.  
  861. static void
  862. SetTabs(w, tab_count, tabs)
  863. Widget w;
  864. int tab_count;
  865. short *tabs;
  866. {
  867.   myAsciiSinkObject sink = (myAsciiSinkObject) w;
  868.   int i;
  869.   Atom XA_FIGURE_WIDTH;
  870.   unsigned long figure_width = 0;
  871.   XFontStruct *font = sink->ascii_sink.font;
  872.  
  873. /*
  874.  * Find the figure width of the current font.
  875.  */
  876.  
  877.   XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE);
  878.   if ( (XA_FIGURE_WIDTH != None) && 
  879.        ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) ||
  880.      (figure_width == 0)) ) 
  881.     if (font->per_char && font->min_char_or_byte2 <= '$' &&
  882.     font->max_char_or_byte2 >= '$')
  883.       figure_width = font->per_char['$' - font->min_char_or_byte2].width;
  884.     else
  885.       figure_width = font->max_bounds.width;
  886.  
  887.   if (tab_count > sink->text_sink.tab_count) {
  888.     sink->text_sink.tabs = (Position *)
  889.     XtRealloc((char *) sink->text_sink.tabs,
  890.           (Cardinal) (tab_count * sizeof(Position)));
  891.     sink->text_sink.char_tabs = (short *)
  892.     XtRealloc((char *) sink->text_sink.char_tabs,
  893.           (Cardinal) (tab_count * sizeof(short)));
  894.   }
  895.  
  896.   for ( i = 0 ; i < tab_count ; i++ ) {
  897.     sink->text_sink.tabs[i] = tabs[i] * figure_width;
  898.     sink->text_sink.char_tabs[i] = tabs[i];
  899.   }
  900.     
  901.   sink->text_sink.tab_count = tab_count;
  902.  
  903. #ifndef NO_TAB_FIX
  904.   {  TextWidget ctx = (TextWidget)XtParent(w);
  905.       ctx->text.redisplay_needed = True;
  906.       _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE);
  907.   }
  908. #endif
  909. }
  910. #endif /* XtSpecificationRelease==5 */
  911.